package br.com.merks.service;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;

import javax.persistence.EntityManager;

import org.apache.log4j.Logger;

import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.util.jpa.EntityManagerCreator;
import br.com.merks.Constants;
import br.com.merks.model.Market;
import br.com.merks.model.MarketAnswer;
import br.com.merks.model.MarketComment;
import br.com.merks.model.OptionType;
import br.com.merks.model.Trade;
import br.com.merks.model.User;
import br.com.merks.service.exception.InsufficientFundsException;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;

@Component
/**
 * Implementacao do Servico de Questao
 * Alteracoes
 * @author @date @comment
 *
 */
public class MarketServiceImpl implements MarketService {
	public static final Logger logger = Logger.getLogger(MarketServiceImpl.class);
	/* Componentes */
	private EntityManager entityManager;
	private MailService mailService;
	private TradeService tradeService;
	/* Variaveis */
	
	
	/* Construtores */
	public MarketServiceImpl(EntityManagerCreator emCreator, MailService mailService, TradeService tradeService) {
		this.entityManager = emCreator.getInstance();
		this.mailService = mailService;
		this.tradeService = tradeService;
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.marketService#add(br.com.merks.model.Market)
	 */
	public Market add(Market market) {
		this.entityManager.getTransaction().begin();
		entityManager.persist(market);
		this.entityManager.getTransaction().commit();
		return market;	
	}

	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.marketService#find(br.com.merks.model.Market)
	 */
	public Market find(Market market) {
		return this.entityManager.find(Market.class, market.getId());
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.MarketService#listTopMarkets(int)
	 */
	public List<Market> listTopMarkets(int topSize) {
		return this.entityManager.createNamedQuery("market.findTopMarkets").getResultList();
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.MarketService#listLastMarkets(int)
	 */
	public List<Market> listLastMarkets(int topSize) {
		return this.entityManager.createNamedQuery("market.findLastMarkets").getResultList();
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.marketService#list()
	 */
	public List<Market> list() {
		return this.entityManager.createNamedQuery("market.findAll").getResultList();
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.MarketService#store(br.com.merks.model.Market, java.util.List)
	 */
	public Market store(Market market, List<MarketAnswer> marketAnswers) {
		this.entityManager.getTransaction().begin();
		this.entityManager.persist(market);
		this.entityManager.getTransaction().commit();
		
	
		for (MarketAnswer qa : marketAnswers) {
			this.entityManager.getTransaction().begin();
			qa.setMarketId(market.getId());
			this.entityManager.persist(qa);
			this.entityManager.getTransaction().commit();

			Trade t = new Trade();
			t.setMarketAnswerId(qa.getId());
			t.setUserId(Constants.MARKET_USER);
			t.setOption(OptionType.buy);
			t.setTimestamp(Calendar.getInstance().getTime());
			t.setValue(0);
			t.setTransactionPrice(new BigDecimal(0));
			t.setMarketId(market.getId());
			t.setMerkPrice(qa.getStartValue());
			User u = new User();
			u.setId(Constants.MARKET_USER);
			u.setMerks(new BigDecimal(0));
			
			try {
				this.tradeService.buy(t,u);
			} catch (InsufficientFundsException e) {
			
			}
			
			
			
		}
		
		return market;
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.MarketService#deleteAll()
	 */
	public void deleteAll() {
		
		 DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		 
		 Query query = new Query("Market");
		 
		 for (Entity taskEntity : datastore.prepare(query).asIterable()) {
			 datastore.delete(taskEntity.getKey());
		 }
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.MarketService#findAnswersByMarket(br.com.merks.model.Market)
	 */
	public List<MarketAnswer> findAnswersByMarket(Market market) {
		return this.entityManager.createNamedQuery("answer.findByMarket").setParameter("id",market.getId()).getResultList();
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.MarketService#addMarketComment(br.com.merks.model.MarketComment)
	 */
	public void addMarketComment(MarketComment marketComment) {
		this.entityManager.getTransaction().begin();
		this.entityManager.persist(marketComment);
		this.entityManager.getTransaction().commit();
		
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.MarketService#deleteMarketComment(br.com.merks.model.MarketComment)
	 */
	public MarketComment deleteMarketComment(MarketComment marketComment) {
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		com.google.appengine.api.datastore.Query query = new com.google.appengine.api.datastore.Query("MarketComment",KeyFactory.createKey("MarketComment", marketComment.getId()));
		 for (Entity taskEntity : datastore.prepare(query).asIterable()) {
			 datastore.delete(taskEntity.getKey());
		 }
		return marketComment;
		
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.MarketService#find(br.com.merks.model.MarketComment)
	 */
	public MarketComment find(MarketComment marketComment) {
		return this.entityManager.find(MarketComment.class, marketComment.getId());
	}
	/*
	 * (non-Javadoc)
	 * @see br.com.merks.service.MarketService#listMarketComments(br.com.merks.model.Market)
	 */
	public List<MarketComment> findCommentsByMarket(Market market) {
		return (List<MarketComment>) this.entityManager.createNamedQuery("comment.findByMarket").setParameter("id",market.getId()).getResultList();
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}	
}